package io.sodabox.web;

import io.sodabox.web.oauth.Profile;
import io.sodabox.web.oauth.SocialAuthConfig;
import io.sodabox.web.oauth.SocialAuthManager;
import io.sodabox.web.oauth.strategy.RequestToken;
import io.sodabox.web.oauth.utils.AccessGrant;
import io.sodabox.web.utils.CookieUtil;
import io.sodabox.web.utils.JsonUtil;

import java.io.File;
import java.util.Set;

import org.jboss.netty.handler.codec.http.Cookie;
import org.jboss.netty.handler.codec.http.CookieDecoder;
import org.jboss.netty.handler.codec.http.CookieEncoder;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.vertx.java.core.Handler;
import org.vertx.java.core.buffer.Buffer;
import org.vertx.java.core.file.impl.PathAdjuster;
import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.core.json.JsonObject;
import org.vertx.java.core.logging.Logger;
import org.vertx.java.deploy.Verticle;

public class AppServer extends Verticle{

	private Logger log;
	private String webRootPrefix;
	private boolean gzipFiles;

	private SocialAuthManager authManager;

	@Override
	public void start() throws Exception {

		log = container.getLogger();

		JsonObject appConfig = container.getConfig();
		if(appConfig.size() == 0){
			String configString = loadStaticData(AppConstants.DEFAULT_CONF_FILE);
			appConfig = new JsonObject(configString);
		}

		// set socialAuthManager
		SocialAuthConfig socialAuthConfig = SocialAuthConfig.getDefault();
		socialAuthConfig.load(appConfig.getObject("oauth"));
		authManager = new SocialAuthManager();
		authManager.setSocialAuthConfig(socialAuthConfig);

		vertx.createHttpServer().requestHandler(new Handler<HttpServerRequest>() {

			public void handle(HttpServerRequest req) {

				req.bodyHandler(new Handler<Buffer>(){
					public void handle(Buffer arg0) {
						System.out.println(arg0);
					};
				});
				webRootPrefix = "webroot" + File.separator;
				gzipFiles = false;


				System.out.println("Params are: ");
				for (String key : req.params().keySet()) {
					System.out.println(key + ":" + req.params().get(key));
				}

				String value = req.headers().get(HttpHeaders.Names.COOKIE);
				if (value != null) {
					Set<Cookie> cookies = new CookieDecoder().decode(value);
					for (final Cookie cookie : cookies) {
						System.out.println("cookie : "+cookie.getName()+" / "+cookie.getValue());

					}
				}


				if("/auth".equals(req.path)){

					String target = req.params().get("target");

					try {

						RequestToken requestToken = authManager.getAuthenticationUrl(target);

						if(requestToken.getAccessGrant() != null) {
							CookieEncoder httpCookieEncoder = new CookieEncoder(true);
							httpCookieEncoder.addCookie(
									"requestToken", 
									JsonUtil.getJsonObject(requestToken.getAccessGrant()).encode());
							req.response.headers().put(HttpHeaders.Names.SET_COOKIE, httpCookieEncoder.encode());
						}

						req.response.headers().put(HttpHeaders.Names.CONTENT_TYPE, "text/html; charset=UTF-8");
						req.response.end("<script type='text/javascript'>location.href='"+requestToken.getUrl()+"';</script>");

					} catch (Exception e) {
						e.printStackTrace();
						req.response.headers().put("Content-Type", "text/html; charset=UTF-8");
						req.response.end("<html><body><h1>^^</h1><br>"+e.getMessage()+"</body></html>");
					}

				}else if("/auth/callback".equals(req.path)){

					Set<Cookie> cookies = new CookieDecoder().decode(value);
					AccessGrant accessToken = CookieUtil.getAccessToken(cookies);

					Profile user = new Profile();
					try {

						user = authManager.connect(accessToken.getProviderId(), req.params(), accessToken);

						req.response.headers().put("Content-Type", "text/html; charset=UTF-8");
						req.response.end("<html><body><h1>OKOKOKOKOKOKOK</h1><br><pre>"+user+"</pre></body></html>");


					} catch (Exception e) {
						e.printStackTrace();
						req.response.headers().put("Content-Type", "text/html; charset=UTF-8");
						req.response.end("<html><body><h1>^^</h1><br>"+e.getMessage()+"</body></html>");
					}



				}
			}
		}).listen(8080);

	}

	public void localResponse(HttpServerRequest req) {
		// browser gzip capability check
		String acceptEncoding = req.headers().get("accept-encoding");
		boolean acceptEncodingGzip = acceptEncoding == null ? false : acceptEncoding.contains("gzip");

		String fileName = webRootPrefix + req.path;
		if (req.path.equals("/")) {
			req.response.statusCode = 505;
			req.response.end();
		} else if (!req.path.contains("..")) {
			// try to send *.gz file
			if (gzipFiles && acceptEncodingGzip) {
				File file = new File(PathAdjuster.adjust(fileName + ".gz"));
				if (file.exists()) {
					// found file with gz extension
					req.response.putHeader("content-encoding", "gzip");
					req.response.sendFile(fileName + ".gz");
				} else {
					// not found gz file, try to send uncompressed file
					req.response.sendFile(fileName);
				}
			} else {
				// send not gzip file
				req.response.sendFile(fileName);
			}
		} else {
			req.response.statusCode = 404;
			req.response.end();
		}
	}

	private String loadStaticData(String filename) {
		if (filename == null || filename.isEmpty()) {
			return null;
		}

		Buffer buffer = null;
		String data = null;

		try {
			buffer = vertx.fileSystem().readFileSync(filename);
			data = buffer.getString(0, buffer.length());
		} catch (Exception e) {
			log.error(e.getMessage());
		}

		return data;
	}

}